package net.gdface.facelog;

import net.gdface.facelog.common.ExtractFeatureReturn;
import net.gdface.facelog.db.FaceBean;
import net.gdface.facelog.db.FeatureBean;
import net.gdface.sdk.CodeInfo;
import net.gdface.sdk.EyeInfo;
import net.gdface.sdk.FAngle;
import net.gdface.sdk.FInt2;
import net.gdface.sdk.FRect;
import net.gdface.utils.BaseTypeTransformer;
import net.gdface.utils.BinaryUtils;

import java.nio.ByteBuffer;
import com.google.common.base.Function;

import gu.sql2java.Managers;
/**
 * 类型转换工具类
 * @author guyadong
 *
 */
public class FacelogTypeTransformer extends BaseTypeTransformer{
	/** 从 FaceBean 对应字段生成FRect对象 */
	public static final Function<FaceBean,FRect> FRECT_FUN = new Function<FaceBean,FRect>(){

		@Override
		public FRect apply(FaceBean input) {
			if(null == input){
				return null;
			}
			Integer left = input.getFaceLeft();
			Integer top = input.getFaceTop();
			Integer width = input.getFaceWidth();
			Integer height = input.getFaceHeight();
			if(null ==left || null == top || null == width || null == height){
				return null;
			}
			return new FRect((int) left, (int) top, (int) width, (int) height);
		}};
	public static final Function<FaceBean,EyeInfo> EYEINFO_FUN = new Function<FaceBean,EyeInfo>(){

		@Override
		public EyeInfo apply(FaceBean input) {
			if(null == input){
				return null;
			}
			Integer leftx = input.getEyeLeftx();
			Integer lefty = input.getEyeLefty();
			Integer rightx = input.getEyeRightx();
			Integer righty = input.getEyeRighty();
			if(null ==leftx || null == lefty || null == rightx || null == righty){
				return null;
			}
			return  new EyeInfo((int) leftx, (int) lefty, (int) rightx, (int) righty);
		}};
	public static final Function<FaceBean,FInt2> MOUTHINFO_FUN = new Function<FaceBean,FInt2>(){

		@Override
		public FInt2 apply(FaceBean input) {
			if (null == input || null == input.getMouthX()||null == input.getMouthY()){
				return null;	
			}
			return new FInt2(input.getMouthX().intValue(),input.getMouthY().intValue());
		}}; 
	public static final Function<FaceBean,FInt2> NOSEINFO_FUN = new Function<FaceBean,FInt2>(){

		@Override
		public FInt2 apply(FaceBean input) {
			if (null == input || null == input.getNoseX() || null == input.getNoseY()) {
				return null;
			}
			return new FInt2(input.getNoseX().intValue(),input.getNoseY().intValue());
		}}; 
	public static final Function<FaceBean,FAngle> FANGLE_FUN = new Function<FaceBean,FAngle>(){

		@Override
		public FAngle apply(FaceBean input) {
			if (null == input 
					|| null == input.getAngleYaw() 
					|| null == input.getAnglePitch() 
					|| null == input.getAngleRoll()){
				return null;		
			}
			return new FAngle(
					input.getAngleYaw().intValue(),
					input.getAnglePitch().intValue(),
					input.getAngleRoll().intValue(),
					0);
		}};
	public static final Function<CodeInfo,FaceBean> FACEBEAN_FUN = new Function<CodeInfo,FaceBean>(){

		@Override
		public FaceBean apply(CodeInfo input) {
			if(null == input){
				return null;
			}
			FaceBean output = new FaceBean();
			setAngleInfo(output, input.getAngle());
			setEyeInfo(output, input.getEi());
			setFaceRect(output, input.getPos());
			setMouthInfo(output, input.getMouth());
			setNoseInfo(output,input.getNose());
			output.setExtInfo(null == input.getFacialData() ? null : ByteBuffer.wrap(input.getFacialData()));
			byte[] feature = input.getCode();
			if(null != feature && feature.length != 0){
				String featureMd5 = BinaryUtils.getMD5String(feature);
				output.setFeatureMd5(featureMd5);
			}
			return output;
		}};
	public static final Function<FaceBean,CodeInfo> CODEINFO_FUN = new Function<FaceBean,CodeInfo>(){

		@Override
		public CodeInfo apply(FaceBean input) {
			if(null == input){
				return null;
			}
			CodeInfo output = new CodeInfo();
			output.setAngle(FANGLE_FUN.apply(input));
			output.setEi(EYEINFO_FUN.apply(input));
			output.setMouth(MOUTHINFO_FUN.apply(input));
			output.setNose(NOSEINFO_FUN.apply(input));
			output.setPos(FRECT_FUN.apply(input));
			output.setFacialData(BinaryUtils.getBytesInBuffer(input.getExtInfo()));
			FeatureBean featureBean = Managers.managerOf(FeatureBean.class).loadByPrimaryKey(input.getFeatureMd5());
			if(null != featureBean){
				
				byte[] feature = BinaryUtils.getBytesInBuffer(featureBean.getFeature());
				output.setCode(feature);
			}
			return output;
		}};
	public static final Function<ByteBuffer,FeatureBean> FEATUREBEAN_FUN = new Function<ByteBuffer,FeatureBean>(){
		@Override
		public FeatureBean apply(ByteBuffer input) {
			if(input != null){
				String featureMd5 = BinaryUtils.getMD5String(input);
				return FeatureBean.builder().md5(featureMd5).feature(input).build();
			}
			return null;
		}}; 
	public static final Function<CodeInfo,FeatureBean> CODEINFO_FEATURE_FUN = new Function<CodeInfo,FeatureBean> (){

		@Override
		public FeatureBean apply(CodeInfo input) {
			byte[] code = input.getCode();
			if(input != null && code != null){
				return FEATUREBEAN_FUN.apply(ByteBuffer.wrap(code));
			}
			return null;
		}};
	public static final Function<CodeInfo,ExtractFeatureReturn> CODEINFO_FEATUREINFO_FUN = new Function<CodeInfo,ExtractFeatureReturn> (){

		@Override
		public ExtractFeatureReturn apply(CodeInfo input) {
			ExtractFeatureReturn featureInfo = new ExtractFeatureReturn();
			featureInfo.setFaceBean(FACEBEAN_FUN.apply(input));
			featureInfo.setFeature(input.getCode());
			return featureInfo;
		}};
	public FacelogTypeTransformer() {
		super();
		transTable.put(FaceBean.class, CodeInfo.class, CODEINFO_FUN);
		transTable.put(CodeInfo.class, FaceBean.class, FACEBEAN_FUN);
		transTable.put(ByteBuffer.class, FeatureBean.class, FEATUREBEAN_FUN);
		transTable.put(CodeInfo.class, FeatureBean.class, CODEINFO_FEATURE_FUN);
		transTable.put(CodeInfo.class, ExtractFeatureReturn.class, CODEINFO_FEATUREINFO_FUN);
	}

	/**
	 * 将FRect中的设置人脸位置信息写入 FaceBean 对应字段
	 * 
	 * @param faceBean
	 * @param fr
	 */
	private static void setFaceRect(FaceBean faceBean, FRect fr) {
		faceBean.setFaceLeft(fr.getLeft());
		faceBean.setFaceTop(fr.getTop());
		faceBean.setFaceWidth(fr.getWidth());
		faceBean.setFaceHeight(fr.getHeight());
	}

	/**
	 * 将EyeInfo中的设置人眼位置信息写入 FaceBean 对应字段
	 * 
	 * @param faceBean
	 * @param ei
	 */
	private static void setEyeInfo(FaceBean faceBean, EyeInfo ei) {
		if(null==ei){
			faceBean.setEyeLeftx(null);
			faceBean.setEyeLefty(null);
			faceBean.setEyeRightx(null);
			faceBean.setEyeRighty(null);
		}else{
			faceBean.setEyeLeftx(ei.getLeftx());
			faceBean.setEyeLefty(ei.getLefty());
			faceBean.setEyeRightx(ei.getRightx());
			faceBean.setEyeRighty(ei.getRighty());
		}
	}
	private static void setMouthInfo(FaceBean faceBean, FInt2 mouth) {
		if(null==mouth){
			faceBean.setMouthX(null);
			faceBean.setMouthY(null);		
		}else{
			faceBean.setMouthX(mouth.getX());
			faceBean.setMouthY(mouth.getY());
		}
	}
	private static void setNoseInfo(FaceBean faceBean, FInt2 mouth) {
		if(null==mouth){
			faceBean.setNoseX(null);
			faceBean.setNoseY(null);
		}else{
			faceBean.setNoseX(mouth.getX());
			faceBean.setNoseY(mouth.getY());
		}
	}
	private static void setAngleInfo(FaceBean faceBean, FAngle angle) {
		if(null==angle){
			faceBean.setAngleYaw(null);
			faceBean.setAnglePitch(null);
			faceBean.setAngleRoll(null);
		}else{
			faceBean.setAngleYaw(angle.getYaw());
			faceBean.setAnglePitch(angle.getPitch());
			faceBean.setAngleRoll(angle.getRoll());
		}
	}
}
